package xiaozhi.modules.agent.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import xiaozhi.common.constant.Constant;
import xiaozhi.common.utils.Result;
import org.apache.commons.lang3.StringUtils;
import xiaozhi.modules.agent.dto.AgentChatHistoryDTO;
import xiaozhi.modules.agent.service.AgentChatHistoryService;
import xiaozhi.modules.agent.service.AgentService;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.List;
import java.util.Date;
import java.util.HashMap;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import java.time.Duration;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
import xiaozhi.common.utils.DateUtils;
import xiaozhi.common.utils.MessageUtils;
import xiaozhi.common.exception.ErrorCode;

/**
 * 智能体公共访问控制器
 * 提供无需认证的公共API接口
 */
@Slf4j
@Tag(name = "智能体公共接口")
@AllArgsConstructor
@RestController
@RequestMapping("/public/agent")
public class PublicAgentController {
    
    private final AgentService agentService;
    private final AgentChatHistoryService agentChatHistoryService;
    
    /**
     * 获取客户端IP地址
     */
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        // 多级代理的情况，取第一个IP
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0].trim();
        }
        return ip;
    }
    
    /**
     * 记录访问日志
     */
    private void logAccess(HttpServletRequest request, String agentId, String sessionId) {
        String ip = getClientIp(request);
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        String requestUrl = request.getRequestURI();
        log.info("[Public API Access] IP: {}", ip);
        log.info("[Public API Access] Time: {}", timestamp);
        log.info("[Public API Access] URL: {}", requestUrl);
        log.info("[Public API Access] AgentId: {}", agentId);
        log.info("[Public API Access] SessionId: {}", sessionId);
    }

    /**
     * 获取智能体聊天记录（无需认证）
     * 
     * @param agentId 智能体ID
     * @param sessionId 会话ID
     * @return 聊天记录列表，包含角色区分信息
     */
    @GetMapping("/{agentId}/chat-history/{sessionId}")
    @Operation(summary = "获取智能体聊天记录（无需认证）", 
               description = "返回聊天记录列表，每条记录包含角色信息（用户/智能体）和标识字段，便于前端区分显示")
    public Result<Object> getPublicAgentChatHistory(
            HttpServletRequest request,
            @PathVariable("agentId") @Parameter(description = "智能体ID") String agentId,
            @PathVariable("sessionId") @Parameter(description = "会话ID") String sessionId) {
        
        try {
            // 参数校验
            if (StringUtils.isBlank(agentId) || StringUtils.isBlank(sessionId)) {
                log.warn("[Public API] Missing required parameters: agentId={}, sessionId={}", agentId, sessionId);
                return new Result<>().error("参数不完整，请提供智能体ID和会话ID");
            }
            
            // 记录访问日志
            logAccess(request, agentId, sessionId);
            
            // 查询聊天记录（已包含角色信息）
            List<AgentChatHistoryDTO> result = agentChatHistoryService.getChatHistoryBySessionId(agentId, sessionId);
            
            if (result == null || result.isEmpty()) {
                log.info("[Public API] No chat history found for agentId={}, sessionId={}", agentId, sessionId);
                return new Result<>().error("未找到对应的聊天记录");
            }
            
            log.info("[Public API] Successfully retrieved {} chat history records for agentId={}", result.size(), agentId);
            return new Result<>().ok(result);
            
        } catch (Exception e) {
            log.error("[Public API] Error retrieving chat history for agentId={}, sessionId={}", agentId, sessionId, e);
            return new Result<>().error("获取聊天记录失败：" + e.getMessage());
        }
    }

    /**
     * 获取智能体会话列表（无需认证）
     * 
     * @param agentId 智能体ID
     * @param params 分页参数
     * @return 会话列表
     */
    @GetMapping("/{agentId}/sessions")
    @Operation(summary = "获取智能体会话列表（无需认证）")
    public Result<Object> getPublicAgentSessions(
            HttpServletRequest request,
            @PathVariable("agentId") @Parameter(description = "智能体ID") String agentId,
            @RequestParam Map<String, Object> params) {
        
        try {
            // 参数校验
            if (StringUtils.isBlank(agentId)) {
                log.warn("[Public API] Missing required parameter: agentId");
                return new Result<>().error("参数不完整，请提供智能体ID");
            }
            
            // 补充agentId参数
            params.put("agentId", agentId);
            
            // 确保分页参数有效
            String pageStr = params.getOrDefault(Constant.PAGE, "1").toString();
            String limitStr = params.getOrDefault(Constant.LIMIT, "10").toString();
            
            try {
                Integer.parseInt(pageStr);
                Integer.parseInt(limitStr);
            } catch (NumberFormatException e) {
                log.warn("[Public API] Invalid pagination parameters: page={}, limit={}", pageStr, limitStr);
                return new Result<>().error("分页参数格式错误");
            }
            // 将校验后的分页参数写回，确保底层服务能读取到
            params.put(Constant.PAGE, pageStr);
            params.put(Constant.LIMIT, limitStr);
            
            // 记录访问日志
            logAccess(request, agentId, "N/A");
            
            // 查询会话列表
            Result<Object> result = new Result<>();
            result.ok(agentChatHistoryService.getSessionListByAgentId(params));
            
            log.info("[Public API] Successfully retrieved sessions for agentId={}", agentId);
            return result;
            
        } catch (Exception e) {
            log.error("[Public API] Error retrieving sessions for agentId={}", agentId, e);
            return new Result<>().error("获取会话列表失败：" + e.getMessage());
        }
    }

    /**
     * 下载聊天记录为txt文件（无需认证）
     * 
     * @param agentId 智能体ID
     * @param sessionId 会话ID
     * @param response HTTP响应
     */
    @GetMapping("/{agentId}/chat-history/{sessionId}/download")
    @Operation(summary = "下载聊天记录为txt文件（无需认证）")
    public void downloadPublicChatHistory(
            HttpServletRequest request,
            @PathVariable("agentId") @Parameter(description = "智能体ID") String agentId,
            @PathVariable("sessionId") @Parameter(description = "会话ID") String sessionId,
            HttpServletResponse response) {
        
        try {
            // 参数校验
            if (StringUtils.isBlank(agentId) || StringUtils.isBlank(sessionId)) {
                log.warn("[Public API] Missing required parameters: agentId={}, sessionId={}", agentId, sessionId);
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                return;
            }
            
            // 记录访问日志
            logAccess(request, agentId, sessionId);
            
            // 设置响应头
            response.setContentType("text/plain;charset=UTF-8");
            String fileName = URLEncoder.encode("chat_history.txt", StandardCharsets.UTF_8.toString());
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            
            // 获取聊天记录
            List<AgentChatHistoryDTO> chatHistoryList = agentChatHistoryService.getChatHistoryBySessionId(agentId, sessionId);
            
            if (chatHistoryList == null || chatHistoryList.isEmpty()) {
                log.info("[Public API] No chat history found for agentId={}, sessionId={}", agentId, sessionId);
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                return;
            }
            
            // 写入响应流
            try (OutputStream out = response.getOutputStream()) {
                // 从聊天记录中获取第一条消息的创建时间作为会话时间
                if (!chatHistoryList.isEmpty()) {
                    Date firstMessageTime = chatHistoryList.get(0).getCreatedAt();
                    String sessionTimeStr = DateUtils.format(firstMessageTime, DateUtils.DATE_TIME_PATTERN);
                    out.write((sessionTimeStr + "\n").getBytes(StandardCharsets.UTF_8));
                }
                
                for (AgentChatHistoryDTO message : chatHistoryList) {
                    String role = message.getChatType() == 1 ? MessageUtils.getMessage(ErrorCode.CHAT_ROLE_USER)
                            : MessageUtils.getMessage(ErrorCode.CHAT_ROLE_AGENT);
                    String direction = message.getChatType() == 1 ? ">>" : "<<";
                    Date messageTime = message.getCreatedAt();
                    String messageTimeStr = DateUtils.format(messageTime, DateUtils.DATE_TIME_PATTERN);
                    String content = message.getContent();
                    
                    String line = "[" + role + "]-[" + messageTimeStr + "]" + direction + ":" + content + "\n";
                    out.write(line.getBytes(StandardCharsets.UTF_8));
                }
                
                out.flush();
            }
            
            log.info("[Public API] Successfully downloaded chat history for agentId={}, sessionId={}", agentId, sessionId);
            
        } catch (IOException e) {
            log.error("[Public API] Error downloading chat history for agentId={}, sessionId={}", agentId, sessionId, e);
            try {
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            } catch (Exception ex) {
                log.error("[Public API] Error setting error response", ex);
            }
        } catch (Exception e) {
            log.error("[Public API] Unexpected error downloading chat history for agentId={}, sessionId={}", agentId, sessionId, e);
            try {
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            } catch (Exception ex) {
                log.error("[Public API] Error setting error response", ex);
            }
        }
    }

    /**
     * 获取聊天记录文本内容（无需认证）
     * 
     * @param agentId 智能体ID
     * @param sessionId 会话ID
     * @return 聊天记录文本内容
     */
    @GetMapping("/{agentId}/chat-history/{sessionId}/text")
    @Operation(summary = "获取聊天记录文本内容（无需认证）")
    public Result<Object> getPublicChatHistoryText(
            HttpServletRequest request,
            @PathVariable("agentId") @Parameter(description = "智能体ID") String agentId,
            @PathVariable("sessionId") @Parameter(description = "会话ID") String sessionId) {
        
        try {
            // 参数校验
            if (StringUtils.isBlank(agentId) || StringUtils.isBlank(sessionId)) {
                log.warn("[Public API] Missing required parameters: agentId={}, sessionId={}", agentId, sessionId);
                return new Result<>().error("参数不完整，请提供智能体ID和会话ID");
            }
            
            // 记录访问日志
            logAccess(request, agentId, sessionId);
            
            // 获取聊天记录
            List<AgentChatHistoryDTO> chatHistoryList = agentChatHistoryService.getChatHistoryBySessionId(agentId, sessionId);
            
            if (chatHistoryList == null || chatHistoryList.isEmpty()) {
                log.info("[Public API] No chat history found for agentId={}, sessionId={}", agentId, sessionId);
                return new Result<>().error("未找到对应的聊天记录");
            }
            
            // 构建文本内容
            StringBuilder textContent = new StringBuilder();
            
            // 从聊天记录中获取第一条消息的创建时间作为会话时间
            if (!chatHistoryList.isEmpty()) {
                Date firstMessageTime = chatHistoryList.get(0).getCreatedAt();
                String sessionTimeStr = DateUtils.format(firstMessageTime, DateUtils.DATE_TIME_PATTERN);
                textContent.append(sessionTimeStr).append("\n");
            }
            
            for (AgentChatHistoryDTO message : chatHistoryList) {
                String role = message.getChatType() == 1 ? MessageUtils.getMessage(ErrorCode.CHAT_ROLE_USER)
                        : MessageUtils.getMessage(ErrorCode.CHAT_ROLE_AGENT);
                String direction = message.getChatType() == 1 ? ">>" : "<<";
                Date messageTime = message.getCreatedAt();
                String messageTimeStr = DateUtils.format(messageTime, DateUtils.DATE_TIME_PATTERN);
                String content = message.getContent();
                
                String line = "[" + role + "]-[" + messageTimeStr + "]" + direction + ":" + content + "\n";
                textContent.append(line);
            }
            
            log.info("[Public API] Successfully retrieved chat history text for agentId={}, sessionId={}", agentId, sessionId);
            return new Result<>().ok(textContent.toString());
            
        } catch (Exception e) {
            log.error("[Public API] Error retrieving chat history text for agentId={}, sessionId={}", agentId, sessionId, e);
            return new Result<>().error("获取聊天记录文本失败：" + e.getMessage());
        }
    }

    /**
     * 分析聊天记录情绪（无需认证）
     * 
     * @param agentId 智能体ID
     * @param sessionId 会话ID
     * @return 情绪分析结果
     */
    @GetMapping("/{agentId}/chat-history/{sessionId}/emotion")
    @Operation(summary = "分析聊天记录情绪（无需认证）")
    public Result<Object> analyzeChatEmotion(
            HttpServletRequest request,
            @PathVariable("agentId") @Parameter(description = "智能体ID") String agentId,
            @PathVariable("sessionId") @Parameter(description = "会话ID") String sessionId) {
        
        try {
            // 参数校验
            if (StringUtils.isBlank(agentId) || StringUtils.isBlank(sessionId)) {
                log.warn("[Public API] Missing required parameters: agentId={}, sessionId={}", agentId, sessionId);
                return new Result<>().error("参数不完整，请提供智能体ID和会话ID");
            }
            
            // 记录访问日志
            logAccess(request, agentId, sessionId);
            
            // 获取聊天记录
            List<AgentChatHistoryDTO> chatHistoryList = agentChatHistoryService.getChatHistoryBySessionId(agentId, sessionId);
            
            if (chatHistoryList == null || chatHistoryList.isEmpty()) {
                log.info("[Public API] No chat history found for agentId={}, sessionId={}", agentId, sessionId);
                return new Result<>().error("未找到对应的聊天记录");
            }
            
            // 调用Python情绪分析服务
            Map<String, Object> emotionResult = callEmotionAnalysisService(chatHistoryList);
            
            log.info("[Public API] Successfully analyzed emotion for agentId={}, sessionId={}", agentId, sessionId);
            return new Result<>().ok(emotionResult);
            
        } catch (Exception e) {
            log.error("[Public API] Error analyzing emotion for agentId={}, sessionId={}", agentId, sessionId, e);
            return new Result<>().error("情绪分析失败：" + e.getMessage());
        }
    }

    /**
     * 分析单条消息情绪（无需认证）
     * 
     * @param text 待分析的文本
     * @return 情绪分析结果
     */
    @GetMapping("/emotion/analyze")
    @Operation(summary = "分析单条消息情绪（无需认证）")
    public Result<Object> analyzeTextEmotion(
            HttpServletRequest request,
            @RequestParam("text") @Parameter(description = "待分析的文本") String text) {
        
        try {
            // 参数校验
            if (StringUtils.isBlank(text)) {
                log.warn("[Public API] Missing required parameter: text");
                return new Result<>().error("参数不完整，请提供待分析的文本");
            }
            
            // 记录访问日志
            logAccess(request, "N/A", "N/A");
            
            // 调用Python情绪分析服务
            Map<String, Object> emotionResult = callTextEmotionAnalysisService(text);
            
            log.info("[Public API] Successfully analyzed text emotion");
            return new Result<>().ok(emotionResult);
            
        } catch (Exception e) {
            log.error("[Public API] Error analyzing text emotion", e);
            return new Result<>().error("情绪分析失败：" + e.getMessage());
        }
    }

    /**
     * 调用Python情绪分析服务
     */
    private Map<String, Object> callEmotionAnalysisService(List<AgentChatHistoryDTO> chatHistoryList) {
        try {
            HttpClient client = HttpClient.newBuilder()
                    .connectTimeout(Duration.ofSeconds(10))
                    .build();
            
            ObjectMapper mapper = new ObjectMapper();
            
            // 构建请求数据
            Map<String, Object> requestData = new HashMap<>();
            requestData.put("chat_history", chatHistoryList);
            
            String requestBody = mapper.writeValueAsString(requestData);
            
            HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create("http://localhost:5001/emotion/chat-history"))
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString(requestBody))
                    .timeout(Duration.ofSeconds(30))
                    .build();
            
            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
            
            if (response.statusCode() == 200) {
                JsonNode jsonNode = mapper.readTree(response.body());
                @SuppressWarnings("unchecked")
                Map<String, Object> result = mapper.convertValue(jsonNode, Map.class);
                return result;
            } else {
                log.error("Python emotion analysis service returned status: {}", response.statusCode());
                return createFallbackResult("Python服务调用失败");
            }
            
        } catch (Exception e) {
            log.error("Error calling Python emotion analysis service", e);
            return createFallbackResult("Python服务不可用: " + e.getMessage());
        }
    }

    /**
     * 调用Python文本情绪分析服务
     */
    private Map<String, Object> callTextEmotionAnalysisService(String text) {
        try {
            HttpClient client = HttpClient.newBuilder()
                    .connectTimeout(Duration.ofSeconds(10))
                    .build();
            
            ObjectMapper mapper = new ObjectMapper();
            
            // 构建请求数据
            Map<String, Object> requestData = new HashMap<>();
            requestData.put("text", text);
            
            String requestBody = mapper.writeValueAsString(requestData);
            
            HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create("http://localhost:5001/emotion/analyze"))
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString(requestBody))
                    .timeout(Duration.ofSeconds(30))
                    .build();
            
            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
            
            if (response.statusCode() == 200) {
                JsonNode jsonNode = mapper.readTree(response.body());
                @SuppressWarnings("unchecked")
                Map<String, Object> result = mapper.convertValue(jsonNode, Map.class);
                return result;
            } else {
                log.error("Python text emotion analysis service returned status: {}", response.statusCode());
                return createFallbackTextResult("Python服务调用失败");
            }
            
        } catch (Exception e) {
            log.error("Error calling Python text emotion analysis service", e);
            return createFallbackTextResult("Python服务不可用: " + e.getMessage());
        }
    }

    /**
     * 创建聊天记录情绪分析的备用结果
     */
    private Map<String, Object> createFallbackResult(String message) {
        Map<String, Object> result = new HashMap<>();
        result.put("user_emotion", "neutral");
        result.put("agent_emotion", "neutral");
        result.put("confidence", 0.0);
        result.put("method", "fallback");
        result.put("message", message);
        result.put("error", true);
        return result;
    }

    /**
     * 创建文本情绪分析的备用结果
     */
    private Map<String, Object> createFallbackTextResult(String message) {
        Map<String, Object> result = new HashMap<>();
        result.put("emotion", "neutral");
        result.put("confidence", 0.0);
        result.put("method", "fallback");
        result.put("message", message);
        result.put("error", true);
        return result;
    }
}